package ClientPackage;


import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.*;
import java.security.AlgorithmParameterGenerator;
import java.security.AlgorithmParameters;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.InvalidParameterSpecException;
import java.util.ArrayList;

import javax.crypto.spec.DHParameterSpec;

public class Client {
	
	// Server 
	private InetAddress _serverIp;
	private int _serverPort;
	private PublicKey _serverpubKey; 
	
	// identity information
	private String _userName;
	private String _salt; 
	private String _pubKeyfileName;
	private String _privKeyfileName;
	// local socket object including local ip and port;
	private DatagramSocket _clientSocket;
	
	// online user
	private ArrayList<ClientInfo> _onlineUsers;
	
	// session information
	
	private Client(String configfile) throws Exception{
		
		_clientSocket = new DatagramSocket(); //generate a socket random port number and a ip
		
		InputStream in = new FileInputStream(configfile);
		BufferedReader br = new BufferedReader(new InputStreamReader(in));
				
		_serverIp = InetAddress.getByName(br.readLine().substring(12));
		_serverPort = Integer.parseInt(br.readLine().substring(14));
		
		KeyGenerator kg = new KeyGenerator();
		kg.generateKeys(); //generate two key pairs(for Public Key cryptography)
		
		_pubKeyfileName = "client_public_key";
		_privKeyfileName = "client_private_key";
								
	}
	
	
	
	// Returns a comma-separated string of 3 values.
	// The first number is the prime modulus P.
	// The second number is the base generator G.
	// The third number is bit size of the random exponent L.
	public static String genDhParams() {
	    try {
	        // Create the parameter generator for a 1024-bit DH key pair
	        AlgorithmParameterGenerator paramGen = AlgorithmParameterGenerator.getInstance("DH");
	        paramGen.init(1024);

	        // Generate the parameters
	        AlgorithmParameters params = paramGen.generateParameters();
	        DHParameterSpec dhSpec
	            = (DHParameterSpec)params.getParameterSpec(DHParameterSpec.class);

	        // Return the three values in a string
	        return ""+dhSpec.getP()+","+dhSpec.getG()+","+dhSpec.getL();
	    } catch (NoSuchAlgorithmException e) {
	    } catch (InvalidParameterSpecException e) {
	    }
	    return null;
	}
	
	
	private boolean login(String pw){
		return true;
	}
	private boolean logout(){
		return true;
	}
	private boolean updateList(){
		return true;
	}
	private boolean SendMessage(ClientInfo to, String message){
		return true;
	}
	
	public String getCommand(){
		return "";
		
	}
	// used to listen from network including server's list updating
        // and other clients message request.
	public void run(){
		
	}
	
	public InetAddress getServerIp(){
		return this._serverIp;
	}
	
	// main thread is used to listen user's command
	public static void main(String[] argv){
		Client client;
		try {
			client = new Client("config.txt");				
			String password="";
			BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
			
			//new Thread(new ClientThread(clientSocket)).start(); //spawn a new thread for receiving packets		

			do{			
				System.out.print("Username>>");
				client._userName = input.readLine();
				System.out.print("\nPassword>>");
				password = input.readLine();
            
			  } while(!client.login(password));
                // although clients can try infinit times, server won't give it
                // allow it to login after 3 trials failed in an hour.
		
			

			
			System.out.println("Login success! Now you could start chatting with others.");
			
			boolean logout = false;
			while(!logout){
				 
				if(client.getCommand().equals("List"){
					updateList();					
				} else if (client.getCommand().equals("Message"){
					SendMessage(SimpleClient to, String message)
				} else if (client.getCommand().equals("Logout") {
					Logout();
					logout = true;
				} else {
					;
				}
				
			}
			
			

	    }catch(Exception e){
        	e.printStackTrace();
        }
	}	
}